﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using TY.UC.Common;
using TY.UC.Common.Extension;
using TY.UT.Common.Http;

namespace TY.UC.Http
{
    /// <summary>
    /// 调用内部接口通用的方法
    /// </summary>
    public partial class HttpHelper
    {
        private static readonly string DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36";
        private static readonly string AppToken = "AppToken".GetStrValue();
        #region JsonPostRequest json参数请求

        public static T JsonPostRequest<T>(TyRequestModel m, string url, string token = null)
        {
            m.Sign = ParamEncryption.GetParamSign(m, token);
            return JsonStrPostRequest(m.JsonSe(), url,null,false).JsonDe<T>();
        }

        /// <summary>
        /// 参数请求(支持https请求)
        /// </summary>
        /// <param name="jsonparam">json字符串</param>
        /// <param name="url">请求地址</param>
        /// <param name="cookies">cookies集合</param>
        /// <param name="sign">是否需要签名验证</param>
        /// <returns>请求结果字符串</returns>
        public static string JsonStrPostRequest(string jsonparam, string url, CookieCollection cookies = null, bool sign = true)
        {
            HttpWebRequest myRequest;
            //http、https请求区分
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
                myRequest = WebRequest.Create(url) as HttpWebRequest;
                if (myRequest != null)
                {
                    myRequest.ProtocolVersion = HttpVersion.Version10;
                    //X509Certificate cert = X509Certificate.CreateFromCertFile(ConfigurationManager.AppSettings["certificate"]); //证书存放的绝对路径  
                    //myRequest.ClientCertificates.Add(cert);  
                }
            }
            else
            {
                myRequest = WebRequest.Create(url) as HttpWebRequest;
            }
            if (myRequest == null) return "";
            //设置头信息
            myRequest.Method = "POST";
            myRequest.ContentType = "application/json";
            myRequest.UserAgent = DefaultUserAgent;
            if (sign)
            {
                string timeStamp = GetTimeStamp();
                string nonce = GetRandom();
                myRequest.Headers.Add("timestamp", timeStamp); //发起请求时的时间戳（单位：毫秒）
                myRequest.Headers.Add("nonce", nonce); //发起请求时的时间戳（单位：毫秒）
                //拼接签名数据,将字符串中字符按升序排序
                var sortStr = string.Concat((timeStamp + nonce + AppToken + jsonparam).OrderBy(c => c));
                myRequest.Headers.Add("signature", Md5Helper.Get32Md5Str(sortStr)); //当前请求内容的数字签名
            }
            if (!string.IsNullOrEmpty(jsonparam))
            {
                var buf = Encoding.UTF8.GetBytes(jsonparam);//转成网络流
                myRequest.ContentLength = buf.Length; 
                try
                {
                    //发送表求
                    using (Stream newStream = myRequest.GetRequestStream())
                    {
                        newStream.Write(buf, 0, buf.Length);
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }

            if (cookies != null)
            {
                myRequest.CookieContainer = new CookieContainer();
                myRequest.CookieContainer.Add(cookies);
            }
            string res="";
            try
            {
                //获得接口返回值
                HttpWebResponse myResponse = myRequest.GetResponse() as HttpWebResponse; 
                using (StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8))
                {
                    res = reader.ReadToEnd();
                    myRequest.Abort();
                    myResponse.Close();
                }
            }
            catch(Exception ex)
            {
                LogHelper.WriteLog("Http请求异常:"+new { url,jsonparam},ex);
                throw ex;
            } 
            return res;
        }

        public static T JsonPostRequest<T>(string jsonparam, string url, CookieCollection cookies = null, bool sign = true)
        {
            string res = JsonStrPostRequest(jsonparam, url, cookies,sign);
            return res.JsonDe<T>();
        } 
        #endregion

        #region FileUpload 文件上传
        /// <summary>
        /// 文件上传
        /// </summary>
        /// <returns></returns>
        public static string FileUpload(string url, byte[] bts, string filename, CookieCollection cookies = null, Dictionary<string, string> headers = null)
        {
            //输入url为空时，直接返回null
            if (string.IsNullOrEmpty(url))
            {
                return null;
            }
            string res = string.Empty;
            HttpWebRequest myRequest = null;
            //http、https请求区分
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                myRequest = WebRequest.Create(url) as HttpWebRequest;
                myRequest.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                myRequest = WebRequest.Create(url) as HttpWebRequest;
            }

            //文件上传 随机分隔线
            string boundary = DateTime.Now.Ticks.ToString("X");
            byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
            byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");

            //转成网络流
            byte[] buf = bts;

            //设置头信息
            myRequest.Method = "POST";
            myRequest.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
            myRequest.UserAgent = DefaultUserAgent;

            StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", filename));
            byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
            if (cookies != null)
            {
                myRequest.CookieContainer = new CookieContainer();
                myRequest.CookieContainer.Add(cookies);
            }
            //发送表求
            using (Stream newStream = myRequest.GetRequestStream())
            {
                newStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
                newStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
                newStream.Write(buf, 0, buf.Length);
                newStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
                newStream.Close();
            }

            //获得接口返回值
            HttpWebResponse myResponse = myRequest.GetResponse() as HttpWebResponse;
            using (StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8))
            {
                res = reader.ReadToEnd();
            }

            myResponse.Close();
            return res;
        }
        #endregion
         
        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="param">form表单字典集合</param>
        /// <param name="url">请求地址</param>
        /// <param name="cookies">cookies集合</param>
        /// <param name="headers">httpheader字典集合</param>
        /// <returns>请求结果字符串</returns>
        public static string GetStrRequest(Dictionary<string, string> param, string url, CookieCollection cookies = null,
            Dictionary<string, string> headers = null)
        {
            if (param != null)
            {
                url += "?";
                foreach (var item in param)
                {
                    url += string.Format("{0}={1}&", item.Key, item.Value);
                }
                url = url.Trim('&');
            }

            string res = string.Empty;
            try
            {
                HttpWebRequest myRequest;
                //http、https请求区分
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback =
                        new RemoteCertificateValidationCallback(CheckValidationResult);
                    myRequest = WebRequest.Create(url) as HttpWebRequest;
                    if (myRequest != null) myRequest.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    myRequest = WebRequest.Create(url) as HttpWebRequest;
                }

                //设置头信息
                if (myRequest == null) return res;
                myRequest.Method = "GET";
                myRequest.ContentLength = 0;
                myRequest.ContentType = "application/x-www-form-urlencoded";
                myRequest.UserAgent = DefaultUserAgent;
                if (headers != null)
                {
                    foreach (var item in headers)
                    {
                        myRequest.Headers.Add(string.Format("{0}:{1}", item.Key, item.Value));
                    }
                }
                if (cookies != null)
                {
                    myRequest.CookieContainer = new CookieContainer();
                    myRequest.CookieContainer.Add(cookies);
                }
                //获得接口返回值
                HttpWebResponse myResponse = myRequest.GetResponse() as HttpWebResponse;
                using (StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8))
                {
                    res = reader.ReadToEnd();
                }
                myResponse.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return res;
        }

        #region 私有方法

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain,
            SslPolicyErrors errors)
        {
            return true; //总是接受  
        }

   
        /// <summary>  
        /// 获取时间戳  
        /// </summary>  
        /// <returns></returns>  
        private static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds).ToString();
        }
        /// <summary>  
        /// 获取随机数
        /// </summary>  
        /// <returns></returns>  
        private static string GetRandom()
        {
            Random rd = new Random(DateTime.Now.Millisecond);
            int i = rd.Next(0, int.MaxValue);
            return i.ToString();
        }
        /// <summary>
        /// 计算签名
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <param name="nonce"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string GetSignature(string timeStamp, string nonce, string data)
        {
            //拼接签名数据,将字符串中字符按升序排序
            var sortStr = string.Concat((timeStamp + nonce + AppToken + data).OrderBy(c => c));
            var bytes = Encoding.UTF8.GetBytes(sortStr);
            //使用MD5加密
            var md5Val = MD5.Create().ComputeHash(bytes);
            //把二进制转化为大写的十六进制
            StringBuilder result = new StringBuilder();
            foreach (var c in md5Val)
            {
                result.Append(c.ToString("X2"));
            }
            return result.ToString().ToUpper();
        }
        #endregion
    }

}
